package com.fit.utils.se;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 封装各种生成唯一性ID算法的工具类.
 * @author hcl
 *
 */
public class IdentitiesUtil {

	private static Logger log = LoggerFactory.getLogger(IdentitiesUtil.class);
	
	// AtomicInteger可以在并发情况下达到原子化更新，避免使用了synchronized，而且性能非常高。
	private final static AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
	//AtomicInteger的最大数字
	private final static Integer ATOMIC_INTEGER_MAX = 999999;
	//自增长数更新到最大数
	private final static NumberFormat ATOMIC_INTEGER_NUMBER_FORMAT = NumberFormat.getInstance();
	
	static{
		ATOMIC_INTEGER_NUMBER_FORMAT.setGroupingUsed(false);
		int len = String.valueOf(ATOMIC_INTEGER_MAX).length();
		//设置最大整数位数
		ATOMIC_INTEGER_NUMBER_FORMAT.setMaximumIntegerDigits(len);
		//设置最小整数位数  
		ATOMIC_INTEGER_NUMBER_FORMAT.setMinimumIntegerDigits(len);
	}
	
	
	/**
	 * 获取一个原始的uuid
	 * @param isHx 是否带中划线"-"
	 * @return
	 */
    public static String uuid(boolean isHx) {
    	String uuid = UUID.randomUUID().toString();
        return isHx ? uuid : uuid.replaceAll("-", "");
    }

    /**
     * 获取一个uuid (不带中划线"-")
     * 返回的是一个由十六进制形式组成的且长度为32的字符串
     * @return
     */
    public static String uuid() {
        return uuid(false);
    }
    
    /**
     * 创建多个uuid
     * @param num
     * @return
     */
    public static List<String> uuids(int num){
    	List<String> uuids = new ArrayList<String>();
		for (int i = 0; i < num; i++) {
			uuids.add(uuid());
		}
    	return uuids;
    }
    
    /**
     * 生成一个 6~23位的唯一流水号(时间戳+自增长数)
     * @param timestamp 时间戳
     * @param len 流水号长度
     * @return
     */
    private static String serialNo(String timestamp,int len){
    	int increment = ATOMIC_INTEGER.incrementAndGet();
    	if(increment > ATOMIC_INTEGER_MAX){
    		synchronized (IdentitiesUtil.class) {
    			int currentInt = ATOMIC_INTEGER.get();
    			if(currentInt > ATOMIC_INTEGER_MAX){
    				ATOMIC_INTEGER.set(0);
    			}
    			increment = ATOMIC_INTEGER.incrementAndGet();
			}
    	}
    	String incrementStr = String.valueOf(increment);
    	if(incrementStr.length() < len){
    		incrementStr = ATOMIC_INTEGER_NUMBER_FORMAT.format(increment);
    	}
    	String serialNo = timestamp+incrementStr;
    	serialNo = serialNo.length() == len ? serialNo : StringUtil.replenish(serialNo, len, StringUtil.BEFORE, '0');
    	return serialNo;
    }
    
    
    /**
     * 生成一个 6~23位的唯一流水号(时间+自增长数)
     * 注意：不能在集群下使用该方法,会有机会出现重复的流水号
     * @param len 流水号长度(取值范围：6~23)
     * @return
     */
    public static String serialNoDate(int len){
    	if(len < 6 || len > 23){
    		log.error("生成流水号异常！len={}, len的取值范围为6~23。",len);
    		throw new RuntimeException("生成流水号异常！len="+len+", len的取值范围为6~23。");
    	}
    	String timestamp = TimeUtil.getCurrentDate("yyyyMMddHHmmssSSS");
    	return serialNo(timestamp, len);
    }
    
    /**
     * 生成一个 23位的唯一流水号(时间+自增长数)
     * 注意：不能在集群下使用该方法,会有机会出现重复的流水号
     * @return
     */
    public static String serialNoDate(){
    	return serialNoDate(23);
    }
    
    /**
     * 生成一个 6~19位的唯一流水号(时间戳+自增长数)
     * 注意：不能在集群下使用该方法,会有机会出现重复的流水号
     * @param len 流水号长度(取值范围：6~19)
     * @return
     */
    public static String serialNoTimeStamp(int len){
    	if(len < 6 || len > 19){
    		log.error("生成流水号异常！len={}, len的取值范围为6~19。",len);
    		throw new RuntimeException("生成流水号异常！len="+len+", len的取值范围为6~19。");
    	}
    	String timestamp = String.valueOf(TimeUtil.getTimestamp());
    	return serialNo(timestamp, len);
    }
    
    /**
     * 生成一个 19位的唯一流水号(时间戳+自增长数)
     * 注意：不能在集群下使用该方法,会有机会出现重复的流水号
     * @return
     */
    public static String serialNoTimeStamp(){
    	return serialNoTimeStamp(19);
    }
        
//    
//    public static void main(String[] args) {
//		
//    	
//    	
//    	final SnowflakeIdWorker id = new SnowflakeIdWorker(0,0);
//    	
//    	int len = 1000000;
////    	final List<String> idList = new ArrayList<>(len);
//    	final String[] ids = new String[len];
//    	List<Runnable> listrun = new ArrayList<>();
//    	for(int i=0; i<len; i++){
//    		final int j = i;
//    		listrun.add(new Runnable() {
//    			private int index = j;
//				@Override
//				public void run() {
////					idList.set(index, String.valueOf(id.nextId()));
//					ids[index] = String.valueOf(id.nextId());
////					ids[index] = String.valueOf(serialNoDate());
//				}
//			});
//    	}
//    	
//    	long start = System.currentTimeMillis();
//    	ThreadUtil.syncTaskExecutor(listrun, 100);
//    	
//    	System.out.println("共用时："+(System.currentTimeMillis()-start)+"毫秒");
//    	
//    	
//    	
//    	Set<String> set = new HashSet<>();
//    	
////    	System.out.println("共产生id条数："+idList.size());
//    	
//    	for(int i=0; i<len; i++){
////    		String idstr = idList.get(i);
//    		String idstr = ids[i];
//    		if(set.contains(idstr)){
//    			throw new RuntimeException(idstr+" 是重复的id。");
//    		}else{
//    			set.add(idstr);
//    			System.out.println(idstr);
//    		}
//    	}
//    	System.out.println("完毕");
//    	
//	}
    
    
    
    
}